package com.kehutong.charge.service.impl;

import com.kehutong.charge.service.CommonService;
import com.kehutong.charge.util.CommonClient;
import com.kehutong.charge.util.JDBCUtil;
import com.kehutong.charge.util.enums.*;
import com.kehutong.charge.vo.ChargeOrderManageExcelVO;
import com.kehutong.charge.entity.*;
import com.kehutong.charge.service.ChargeBillHouseService;
import com.kehutong.charge.service.ChargeOrderService;
import com.kehutong.charge.util.CommonUtil;
import com.kehutong.common.DoveClient;
import com.kehutong.common.constant.CommonConstant;
import com.kehutong.common.enums.UserType;
import com.kehutong.common.errcode.Assert;
import com.kehutong.common.errcode.Result;
import com.kehutong.common.excel.tool.ExcelTool;
import com.kehutong.common.util.ListUtils;
import com.kehutong.common.util.Token;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.entity.FindArray;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;

/**
 * @program: kht
 * @description: ChargeOrderServiceImpl
 * @author: joneron
 * @create: 2021/7/5
 **/
public class ChargeOrderServiceImpl implements ChargeOrderService {

    private static final Logger logger = LoggerFactory.getLogger(ChargeOrderServiceImpl.class);

    @Inject
    private JdbcSession jdbcSession;
    @Inject
    private DoveClient doveClient;
    @Inject
    ChargeBillHouseService chargeBillHouseService;
    @Inject
    ExcelTool excelTool;
    @Inject
    CommonService commonService;
    @Inject
    CommonClient commonClient;


    @Override
    public Page<ChargeOrderManage> findPage(JSONObject jsonObject) {
        String search = jsonObject.getString("search");
        FindPage<ChargeOrderManage> find = jdbcSession.findPage(ChargeOrderManage.class)
                .eq("deleted", false)
                .eq(jsonObject,"communityNo")
                .eq(jsonObject,"orderStatus")
                .like(jsonObject,"orderYearMonth")
                .eq(jsonObject,"userNo")
                .like(jsonObject,"orderNo")
                .eq(jsonObject,"orderOrigin")
                .eq(jsonObject,"payMethod");

        Token token = jsonObject.getObject("token", Token.class);
        if(null != token && token.getUserType().equals(UserType.webwork)){
            try {
                JSONArray stewardHouseNos = commonClient.getStewardHouseNos(token.getUuid());
                find.in("houseNo",stewardHouseNos);
            } catch (Exception e) {
                logger.error("获取管家楼栋异常");
                throw new RuntimeException(e);
            }
        }else {
            find.eq(jsonObject,"houseNo");
        }

        // 处理时间
        JDBCUtil.between(jsonObject, find, "createTime");

        if(!Objects.isEmpty(search)){
            find.markBegin();
            find.like("communityName", search).or();
            find.like("chargeName", search).or();
            find.like("createTime", search).or();
            find.markEnd();
        }

        //添加选中导出条件
        JSONArray exportIdList = jsonObject.getJSONArray("exportIdList");
        if(!Objects.isEmpty(exportIdList)){
            find.in("orderNo",exportIdList);
        }
        find.order("createTime", "desc").page(jsonObject);
        return find.exe();
    }


    @Override
    public void pageExport(HttpServletRequest req, HttpServletResponse resp, JSONObject jsonObject) {
        jsonObject.put("pageNo", 1);
        jsonObject.put("pageSize", ExcelTool.MAX_ROWS);
        List<ChargeOrderManage> list = findPage(jsonObject).getList();
        Assert.notEmpty(list,"导出失败！没有找到相关的常规订单数据.");
        List<ChargeOrderManageExcelVO> dtoList = ListUtils.copyList(list, ChargeOrderManageExcelVO::new);
        excelTool.excelDownload(req,resp,dtoList,"常规订单列表导出");
    }


    @Override
    public List<ChargeOrderManage> findList(JSONObject jsonObject) {

        FindArray<ChargeOrderManage> manageList = jdbcSession.findArray(ChargeOrderManage.class)
                .eq("deleted", false)
                .eq(jsonObject,"userNo")
                .eq(jsonObject,"houseBillNo")
                .eq(jsonObject,"orderYearMonth")
                .like(jsonObject,"createTime")
                .eq(jsonObject,"orderStatus");

        return manageList.exe();
    }

    /**
     * 支付接口处理
     * @param orderManage
     * @return
     */
    @Override
    public Object save(ChargeOrderManage orderManage) {

        List<ChargeOrderManage> orders = jdbcSession.findArray(ChargeOrderManage.class)
                .eq("deleted",false)
                .eq("houseBillNo",orderManage.getHouseBillNo())
                .eq("orderStatus", ChargeOrderStatusEnum.ORDER_WAIT_PAY.getId())
                .exe();

        if(Objects.isEmpty(orders)){
            //查询账单数据
            ChargeBillHouse billHouse = jdbcSession.findOne(ChargeBillHouse.class)
                    .eq("deleted",false)
                    .eq("houseBillNo",orderManage.getHouseBillNo())
                    .exe();

            //1、生成订单
            orderManage.setOrderStatus(ChargeOrderStatusEnum.ORDER_WAIT_PAY);
            orderManage.setPayableAmount(orderManage.getBillAmount());
            orderManage.setCommunityName(billHouse.getCommunityName());
            orderManage.setOrderYearMonth(billHouse.getBillYearMonth());
            orderManage.setBillAmount(billHouse.getBillAmount());
            orderManage.setPayableAmount(billHouse.getBillAmountUnPaid());
            orderManage.setCommunityBillNo(billHouse.getCommunityBillNo());
            orderManage.setHouseNo(billHouse.getHouseNo());
            orderManage.setOptStatus(ChargeOrderStatusEnum.ORDER_REFUND_NOT);
            orderManage.setBuildNo(billHouse.getBuildNo());
            orderManage.setResidentsType(billHouse.getResidentsType());
            orderManage.setPayMethod(CommonEnum.COM_PAY_NOT);

            boolean isSuccess = jdbcSession.insert(orderManage)==1;

            //3、添加操作日志
            commonService.insetLogger(orderManage.getOrderNo(),
                    ChargeLogEnum.LOG_CHARGE_ORDER_COM.getDesc(),
                    "添加订单数据",
                    ChargeOrderStatusEnum.ORDER_WAIT_PAY.getDesc(),
                    ChargeOrderStatusEnum.ORDER_REFUND_NOT.getDesc(), isSuccess?"成功":"失败", orderManage.getCreateName());
            return orderManage.getOrderNo();
        }else{
            return orders.get(0).getOrderNo();
        }
    }

    @Override
    public Object update(ChargeOrderManage chargeOrderManage) {

        if(chargeOrderManage.getOrderStatus().equals(ChargeOrderStatusEnum.ORDER_CLOSE)){
            //添加操作日志
            commonService.insetLogger(chargeOrderManage.getOrderNo(),
                    ChargeLogEnum.LOG_CHARGE_ORDER_COM.getDesc(),
                    "订单数据",
                    ChargeOrderStatusEnum.ORDER_CLOSE.getDesc(),
                    chargeOrderManage.getOptStatus().getDesc(),"关闭订单（备注内容："+chargeOrderManage.getCloseRemark()+")",chargeOrderManage.getUpdateName());

            //修改状态
            return Result.success(jdbcSession.updateById(chargeOrderManage));
        }


        //修改费用
        ChargeOrderManage orderManage = jdbcSession.findById(ChargeOrderManage.class,chargeOrderManage.getId());

        //1、查詢是否有配置数据
        ChargeFeeConfig config= jdbcSession.findOne(ChargeFeeConfig.class)
                .eq("deleted", false)
                .eq("communityNo",orderManage.getCommunityNo())
                .eq("status",true).exe();

        //添加费用信息
        ChargeFeeManage manage = Pool.newInstance(ChargeFeeManage.class);

        if(null != config ){
            //需要审核
            if(config.getApproveMethod().getId().equals(EnableStateEnum.UNUSED.getId())){
                manage.setApplyStatus(FeeStatusEnum.CS_UN_TREATED);
                manage.setApplyName(config.getApplyName());
                manage.setApplyUserNo(config.getApplyUserNo());
            }else{
                manage.setApplyStatus(FeeStatusEnum.CS_SUCCESS);
            }
        }else{
            return Result.error(1231,"请先设置费用模板信息！");
        }

        BigDecimal amounts = orderManage.getPayableAmount().subtract(orderManage.getNegotiateAmount());
        orderManage.setNegotiateAmount(chargeOrderManage.getNegotiateAmount());
        if(manage.getApplyStatus().getId().equals(FeeStatusEnum.CS_SUCCESS.getId())){
            orderManage.setPayableAmount(amounts);  //成功了修改订单金额否则在审批通过的时候修改
        }
        jdbcSession.updateById(orderManage);
        manage.setServiceNo(CommonUtil.generateRandom("FC"));
        manage.setOrderNo(orderManage.getOrderNo());
        manage.setBillAmount(orderManage.getBillAmount());
        manage.setNegotiateAmount(amounts);
        manage.setReason(orderManage.getRemark());
        manage.setCreateName(chargeOrderManage.getUpdateName());
        manage.setDepartmentName(orderManage.getDepartmentName());
        manage.setDepartmentNo(orderManage.getDepartmentNo());
        manage.setDepartmentNos(orderManage.getDepartmentNos());

        return jdbcSession.insert(manage);
    }

    @Override
    public Object deleteById(String id) {
        ChargeOrderManage result = Pool.get(ChargeOrderManage.class, id);
        if (result != null) {
            result.setDeleted(true);
            jdbcSession.updateById(result);
        }
        return 1;
    }


    @Override
    public ChargeOrderManage findOrderDetail(JSONObject jsonObject) {
        ChargeOrderManage orderManage = jdbcSession.findOne(ChargeOrderManage.class)
                .eq("deleted",false)
                .eq(jsonObject,"houseBillNo")
                .eq(jsonObject,"orderStatus")
                .eq(jsonObject,"userNo")
                .eq(jsonObject,"orderNo")
                .eq(jsonObject,"optStatus")
                .exe();

        return orderManage;
    }



    @Override
    public Object submitBillPay(JSONObject jsonObject, Token token) {

        //1、创建管理订单
        ChargeOrderManage orderManage = Pool.newInstance(ChargeOrderManage.class);
        //生成订单号
        String orderNo = CommonUtil.generateRandom("DD");
        orderManage.setOrderNo(orderNo);
        orderManage.setCreateName(token.getUsername());
//        orderManage.setUserNo(token.getUuid());
//        orderManage.setChargeName(token.getUsername());
        orderManage.setOrderStatus(ChargeOrderStatusEnum.ORDER_WAIT_PAY);
        orderManage.setHouseBillNo(jsonObject.getString("houseBillNo"));
        orderManage.setCommunityNo(jsonObject.getString("communityNo"));
        orderManage.setHouseNo(jsonObject.getString("houseNo"));
        orderManage.setOptStatus(ChargeOrderStatusEnum.ORDER_REFUND_NOT);

        //2、创建子订单
        JSONArray jsonArray = jsonObject.getJSONArray("itemBillNoList");
        for (int i = 0; i < jsonArray.size(); i++) {

            JSONObject obj = (JSONObject)jsonArray.get(i);

            ChargeOrderItem orderItem = Pool.newInstance(ChargeOrderItem.class);
            orderItem.setOrderNo(orderNo);
            String orderItemNo = CommonUtil.generateRandom("DD");
            orderItem.setOrderItemNo(orderItemNo);
//            orderItem.setUserNo(token.getUuid());
//            orderItem.setChargeName(token.getUsername());
            orderItem.setOrderStatus(ChargeOrderStatusEnum.ORDER_WAIT_PAY);
            orderItem.setHouseBillNo(obj.getString("houseBillNo"));
            orderItem.setCommunityNo(obj.getString("communityNo"));
            orderItem.setItemBillNo(obj.getString("itemBillNo"));

            jdbcSession.insert(orderItem);
        }

        jdbcSession.insert(orderManage);

        //2、修改账单状态


        return orderNo;
    }

    @Override
    public Object findConfigPage(JSONObject jsonObject) {
        this.initDefaultConfig();
        FindPage<ChargeOrderConfig> find = jdbcSession.findPage(ChargeOrderConfig.class)
                .eq("deleted", false)
                .eq(jsonObject,"communityNo")
                .eq(jsonObject,"status")
                .order("sort", "desc")
                .order("createTime", "desc");
        return find.page(jsonObject).exe();
    }


    private void initDefaultConfig(){
        ChargeOrderConfig communityNo = jdbcSession.findOne(ChargeOrderConfig.class)
                //.eq("deleted",false) 需求变更，删除后不可再次初始化
                .eq("communityNo", CommonConstant.DEFAULT_COMMUNITY_NO)
                .eq("initData", true)
                .exe();
        if(null != communityNo){
            return;
        }
        ChargeOrderConfig config = Pool.newInstance(ChargeOrderConfig.class);
        config.setCommunityNo(CommonConstant.DEFAULT_COMMUNITY_NO);
        config.setCommunityName(CommonConstant.DEFAULT_COMMUNITY_NAME);
        config.setCreateName("System");
        config.setCgOrderMinute("30");
        config.setLsOrderMinute("30");
        config.setOrderDays("7");
        config.setStatus(true);
        config.setSort(999);
        config.setInitData(true);
        jdbcSession.insert(config);
    }



    @Override
    public Object saveConfig(ChargeOrderConfig config) {
        if(CommonConstant.DEFAULT_COMMUNITY_NAME.equals(config.getCommunityNo())){
            //如果是添加默认配置
            config.setCommunityNo(CommonConstant.DEFAULT_COMMUNITY_NO);
            config.setInitData(true);
            config.setSort(999);
        }
        return jdbcSession.insert(config);
    }

    @Override
    public Object updateConfig(ChargeOrderConfig config) {
        if(config.isInitData() && !CommonConstant.DEFAULT_COMMUNITY_NO.equals(config.getCommunityNo())){
            throw new RuntimeException("系统初始化数据不能修改ID.");
        }
        return jdbcSession.updateById(config);
    }

    @Override
    public Object delConfigById(String id) {
        ChargeOrderConfig result = Pool.get(ChargeOrderConfig.class, id);
        if (result != null) {
            result.setDeleted(true);
            jdbcSession.updateById(result);
        }
        return Result.success();
    }


}
